// kml  =>  geojson

var removeSpace = /\s*/g,
    trimSpace = /^\s*|\s*$/g,
    splitSpace = /\s+/
    // generate a short, numeric hash of a string
function okhash(x) {
    if (!x || !x.length) return 0
    for (var i = 0, h = 0; i < x.length; i++) {
        h = ((h << 5) - h + x.charCodeAt(i)) | 0
    }
    return h
}
// all Y children of X
function get(x, y) {
    return x.getElementsByTagName(y)
}

function attr(x, y) {
    return x.getAttribute(y)
}

function attrf(x, y) {
    return parseFloat(attr(x, y))
}
// one Y child of X, if any, otherwise null
function get1(x, y) {
    var n = get(x, y)
    return n.length ? n[0] : null
}
// https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize
function norm(el) {
    if (el.normalize) {
        el.normalize()
    }
    return el
}
// cast array x into numbers
function numarray(x) {
    for (var j = 0, o = []; j < x.length; j++) {
        o[j] = parseFloat(x[j])
    }
    return o
}
// get the content of a text node, if any
function nodeVal(x) {
    if (x) {
        norm(x)
    }
    return (x && x.textContent) || ''
}

// get the contents of multiple text nodes, if present
// function getMulti(x, ys) {
//   var o = {},
//     n,
//     k
//   for (k = 0; k < ys.length; k++) {
//     n = get1(x, ys[k])
//     if (n) o[ys[k]] = nodeVal(n)
//   }
//   return o
// }

// add properties of Y to X, overwriting if present in both
// function extend(x, y) {
//   for (var k in y) x[k] = y[k]
// }
// get one coordinate from a coordinate array, if any
function coord1(v) {
    return numarray(v.replace(removeSpace, '').split(','))
}
// get all coordinates from a coordinate array as [[],[]]
function coord(v) {
    var coords = v.replace(trimSpace, '').split(splitSpace),
        o = []
    for (var i = 0; i < coords.length; i++) {
        o.push(coord1(coords[i]))
    }
    return o
}
// function coordPair(x) {
//   var ll = [attrf(x, 'lon'), attrf(x, 'lat')],
//     ele = get1(x, 'ele'),
//     // handle namespaced attribute in browser
//     heartRate = get1(x, 'gpxtpx:hr') || get1(x, 'hr'),
//     time = get1(x, 'time'),
//     e
//   if (ele) {
//     e = parseFloat(nodeVal(ele))
//     if (!isNaN(e)) {
//       ll.push(e)
//     }
//   }
//   return {
//     coordinates: ll,
//     time: time ? nodeVal(time) : null,
//     heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null,
//   }
// }

// create a new feature collection parent object
function fc() {
    return {
        type: 'FeatureCollection',
        features: [],
    }
}

var serializer
if (typeof XMLSerializer !== 'undefined') {
    /* istanbul ignore next */
    serializer = new XMLSerializer()
        // only require xmldom in a node environment
} else if (typeof exports === 'object' && typeof process === 'object' && !process.browser) {
    serializer = new(require('xmldom').XMLSerializer)()
}

function xml2str(str) {
    // IE9 will create a new XMLSerializer but it'll crash immediately.
    // This line is ignored because we don't run coverage tests in IE9
    /* istanbul ignore next */
    if (str.xml !== undefined) return str.xml
    return serializer.serializeToString(str)
}


export function kmlToGeoJSON(doc, data) {
    var from = data
    var placemarks = get(doc, 'Placemark')

    for (var key in from) {
        if (typeof from[key] == 'string' && key != 'Placemark' && key != 'positionsArr') {
            from[key] = nodeVal(get1(doc, 'wpml:' + key))
        } else if (typeof from[key] == 'object' && key != 'Placemark' && key != 'positionsArr') {
            for (var childrenKey in from[key]) {
                if (typeof from[key][childrenKey] == 'string') {
                    from[key][childrenKey] = nodeVal(get1(doc, 'wpml:' + childrenKey))
                }
            }
        } else if (key == 'Placemark') {
            for (var j = 0; j < placemarks.length; j++) {
                from[key].push(getPlacemark(placemarks[j]))
            }
        }
    }

    function getPlacemark(root) {
        // 待处理 ----------------------------------------------------
        var Placemark = {
            Point: {
                coordinates: ''
            }, // 航点经纬度<经度,纬度> *
            index: '', // 航点序号 *
            useGlobalHeight: '', // 	是否使用全局高度 *
            // 建图航拍模板元素
            ellipsoidHeight: '', // 全局航线高度（相对起飞点高度） *
            height: '', // 航点高度（EGM96海拔高度/相对起飞点高度/AGL相对地面高度） *
            useGlobalSpeed: '', // 是否使用全局飞行速度 *
            waypointSpeed: '', // 航点飞行速度 *
            useGlobalHeadingParam: '', // 是否使用全局偏航角模式参数 *
            waypointHeadingParam: { // 偏航角模式参数 *
                waypointHeadingMode: '', // 飞行器偏航角模式 *
                waypointHeadingAngle: '', // 飞行器偏航角模式 *
                waypointHeadingPathMode: '', // 飞行器偏航角转动方向 *
                waypointPoiPoint: '', //
                waypointHeadingPoiIndex: '', //
            },
            useGlobalTurnParam: '', // 	是否使用全局航点类型（全局航点转弯模式） *
            waypointTurnParam: { // 航点类型（航点转弯模式） *
                waypointTurnMode: '', // 航点类型（航点转弯模式） *
                waypointTurnDampingDist: '', // 航点转弯截距 *
            },
            useStraightLine: '', // 	该航段是否贴合直线 *
            gimbalPitchAngle: '', // 航点云台俯仰角 *
            actionGroup: [] // 航线初始动作 
        }
        var actionGroup = get(root, 'wpml:actionGroup')
        for (var key in Placemark) {
            if (typeof Placemark[key] == 'string' && key != 'actionGroup') {
                Placemark[key] = nodeVal(get1(root, 'wpml:' + key))
            } else if (typeof Placemark[key] == 'object' && key != 'actionGroup') {
                for (var childrenKey in Placemark[key]) {
                    if (typeof Placemark[key][childrenKey] == 'string' && key != 'Point') {
                        Placemark[key][childrenKey] = nodeVal(get1(root, 'wpml:' + childrenKey))
                    } else if (key == 'Point') {
                        Placemark[key][childrenKey] = nodeVal(get1(root, key)).trim()
                        from.positionsArr.push(coord1(nodeVal(get1(root, key)) + ',' + nodeVal(get1(root, 'wpml:ellipsoidHeight'))))
                    }
                }
            } else if (key == 'actionGroup') {
                for (var j = 0; j < actionGroup.length; j++) {
                    Placemark[key].push(getActionGroup(actionGroup[j]))
                }
            }
        }
        return Placemark
    }

    function getActionGroup(root) {
        var actionGroup = { // 航线初始动作
            actionGroupId: '', // 动作组id *
            actionGroupStartIndex: '', // 动作组开始生效的航点 *
            actionGroupEndIndex: '', // 动作组结束生效的航点 *
            actionGroupMode: '', // 动作执行模式 *
            actionTrigger: {
                actionTriggerType: '', // 动作触发器类型 *
                actionTriggerParam: '', // 动作触发器参数
            }, // 动作组触发器 *
            action: [], // 动作列表
        }
        var actions = get(root, 'wpml:action')

        for (var key in actionGroup) {
            if (typeof actionGroup[key] == 'string' && key != 'action') {
                actionGroup[key] = nodeVal(get1(root, 'wpml:' + key))
            } else if (typeof actionGroup[key] == 'object' && key != 'action') {
                for (var childrenKey in actionGroup[key]) {
                    if (typeof actionGroup[key][childrenKey] == 'string') {
                        actionGroup[key][childrenKey] = nodeVal(get1(root, 'wpml:' + childrenKey))
                    }
                }
            } else if (key == 'action') {
                for (var j = 0; j < actions.length; j++) {
                    actionGroup[key].push(getActions(actions[j]))
                }
            }
        }
        return actionGroup
    }

    function getActions(root) {
        var action = {
            actionId: '', // 动作id *
            actionActuatorFunc: '', // 动作类型 *
            actionActuatorFuncParam: { // 动作参数
                payloadPositionIndex: '', // 负载挂载位置 *
                // ----------- takePhoto/startRecord/stopRecord ---------------------
                fileSuffix: '', // 拍摄照片 或者 视频 文件后缀 *
                payloadLensIndex: '', // 拍摄照片 或者 视频 存储类型 *
                useGlobalPayloadLensIndex: '', // 是否使用全局存储类型 *
                // ----------- focus ---------------------
                isPointFocus: '', // 是否使用全局存储类型 *
                focusX: '', // 对焦点位置 *
                focusY: '', // 对焦点位置 *
                focusRegionWidth: '', // 对焦区域宽度比 *
                focusRegionHeight: '', // 对焦区域高度比 *
                isInfiniteFocus: '', // 是否无穷远对焦 *
                // ----------- zoom ---------------------
                focalLength: '', // 变焦焦距 *
                // ----------- customDirName ---------------------
                directoryName: '', // 新文件夹的名称 *
                // ----------- gimbalRotate/gimbalEvenlyRotate ---------------------
                gimbalHeadingYawBase: '', // 云台偏航角转动坐标系 *
                gimbalRotateMode: '', // 云台转动模式 *
                gimbalPitchRotateEnable: '', // 是否使能云台Pitch转动 *
                gimbalPitchRotateAngle: '', // 云台Pitch转动角度 *
                gimbalRollRotateEnable: '', // 是否使能云台Roll转动 *
                gimbalRollRotateAngle: '', // 云台Roll转动角度 *
                gimbalYawRotateEnable: '', // 是否使能云台Yaw转动 *
                gimbalYawRotateAngle: '', // 云台Yaw转动角度 *
                gimbalRotateTimeEnable: '', // 是否使能云台转动时间 *
                gimbalRotateTime: '', // 云台完成转动用时 *
                // ----------- rotateYaw/orientedShoot ---------------------
                aircraftHeading: '', // 飞行器目标偏航角（相对于地理北） *
                aircraftPathMode: '', // 飞行器偏航角转动模式 *
                accurateFrameValid: '', // 是否框选精准复拍目标 *
                targetAngle: '', // 目标框角度 *
                actionUUID: '', // 动作唯一标识 *
                imageWidth: '', // 照片宽度 *
                imageHeight: '', // 照片高度 *
                AFPos: '', // 	AF电机位置 *
                gimbalPort: '', // 	云台端口号 *
                orientedCameraType: '', // 	相机类型 *
                orientedFilePath: '', // 	照片文件路径 *
                orientedFileMD5: '', // 	照片文件MD5 *
                orientedFileSize: '', // 	照片文件大小 *
                orientedFileSuffix: '', // 	照片文件后缀 *
                orientedPhotoMode: '', // 拍照模式 *
                // ----------- hover ---------------------
                hoverTime: '', // 飞行器悬停等待时间 *
            },
        }
        for (var key in action) {
            if (typeof action[key] == 'string') {
                action[key] = nodeVal(get1(root, 'wpml:' + key))
            } else if (typeof action[key] == 'object') {
                for (var childrenKey in action[key]) {
                    if (typeof action[key][childrenKey] == 'string') {
                        action[key][childrenKey] = nodeVal(get1(root, 'wpml:' + childrenKey))
                    }
                }
            }
        }
        if (action.actionActuatorFunc === 'orientedShoot') {
            action.actionActuatorFuncParam['gshx'] = action.actionActuatorFuncParam.useGlobalPayloadLensIndex == 1 ? true : false
            action.actionActuatorFuncParam['gshxW'] = action.actionActuatorFuncParam.useGlobalPayloadLensIndex == 1 || action.actionActuatorFuncParam.payloadLensIndex === 'wide,zoom' || action.actionActuatorFuncParam.payloadLensIndex === 'wide' ? true : false
            action.actionActuatorFuncParam['gshxZ'] = action.actionActuatorFuncParam.useGlobalPayloadLensIndex == 1 || action.actionActuatorFuncParam.payloadLensIndex === 'wide,zoom' || action.actionActuatorFuncParam.payloadLensIndex === 'zoom' ? true : false
            action.actionActuatorFuncParam['psjd'] = action.actionActuatorFuncParam.gimbalYawRotateAngle * 1 - action.actionActuatorFuncParam.aircraftHeading * 1
            action.actionActuatorFuncParam['xjbj'] = action.actionActuatorFuncParam.focalLength * 1 / 24
        } else if (action.actionActuatorFunc === 'takePhoto' || action.actionActuatorFunc === 'startRecord') {
            action.actionActuatorFuncParam['gshx'] = action.actionActuatorFuncParam.useGlobalPayloadLensIndex == 1 ? true : false
            action.actionActuatorFuncParam['gshxW'] = action.actionActuatorFuncParam.useGlobalPayloadLensIndex == 1 || action.actionActuatorFuncParam.payloadLensIndex === 'wide,zoom' || action.actionActuatorFuncParam.payloadLensIndex === 'wide' ? true : false
            action.actionActuatorFuncParam['gshxZ'] = action.actionActuatorFuncParam.useGlobalPayloadLensIndex == 1 || action.actionActuatorFuncParam.payloadLensIndex === 'wide,zoom' || action.actionActuatorFuncParam.payloadLensIndex === 'zoom' ? true : false
        } else if (action.actionActuatorFunc === 'zoom') {
            action.actionActuatorFuncParam['xjbj'] = Math.floor(action.actionActuatorFuncParam.focalLength * 1) / 24
        }
        return action
    }
    return from
}